﻿using UnityEditor;
using UnityEngine;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using LuaFramework;
using System;

public class Packager
{
	public static string platform = string.Empty;
	static List<string> paths = new List<string> ();
	static List<string> files = new List<string> ();
	static List<AssetBundleBuild> maps = new List<AssetBundleBuild> ();

	///-----------------------------------------------------------
	static string[] exts = { ".txt", ".xml", ".lua", ".assetbundle", ".json" };

	static bool CanCopy (string ext)
	{   //能不能复制
		foreach (string e in exts) {
			if (ext.Equals (e))
				return true;
		}
		return false;
	}

	/// <summary>
	/// 载入素材
	/// </summary>
	static UnityEngine.Object LoadAsset (string file)
	{
		if (file.EndsWith (".lua"))
			file += ".txt";
		return AssetDatabase.LoadMainAssetAtPath ("Assets/LuaFramework/Examples/Builds/" + file);
	}

	[MenuItem ("LuaFramework/全部资源打包",false,1)]
	public static void DevelpmentAllBuild ()
	{
		BuildAssetResource (getTarget ());
	}

	[MenuItem ("LuaFramework/开发快速打包",false,1)]
	public static void DevelpmentBuild ()
	{
		EditorWindow.GetWindow (typeof(LwtWindows));
	}

	[MenuItem ("LuaFramework/填写CSV",false,2)]
	public static void AutoWriteCsv ()
	{
		AutoWriteCsv window = (AutoWriteCsv)EditorWindow.GetWindow (typeof(AutoWriteCsv));
		window.position = new Rect (400, 200, 1000, 700);  // 窗口的坐标 
	}

	public static void BuildAssetResource (string str)
	{
		
	}

	public static BuildTarget getTarget ()
	{
		BuildTarget target = BuildTarget.StandaloneWindows;
		#if UNITY_STANDALONE_WIN
		target = BuildTarget.StandaloneWindows;
		#elif UNITY_ANDROID
			target = BuildTarget.Android;
		#elif UNITY_IOS
		#if UNITY_5
				target = BuildTarget.iOS;
		#else
				target = BuildTarget.iPhone;
		#endif
		#endif
		return target;
	}

	/// <summary>
	/// 生成绑定素材
	/// </summary>
	public static void BuildAssetResource (BuildTarget target)
	{
		if (Directory.Exists (Util.DataPath)) {
			Directory.Delete (Util.DataPath, true);
		}
		string streamPath = Application.streamingAssetsPath;
		if (Directory.Exists (streamPath)) {
			Directory.Delete (streamPath, true);
		}
		Directory.CreateDirectory (streamPath);
		AssetDatabase.Refresh ();

		FileInfo[] fileInfos = null;
		if (Directory.Exists (AppConst.csv_path)) {  
			DirectoryInfo direction = new DirectoryInfo (AppConst.csv_path);  
			fileInfos = direction.GetFiles ("*", SearchOption.AllDirectories);  
		}
		if (fileInfos != null) {
			for (int i = 0; i < fileInfos.Length; i++) {
				if (fileInfos [i].Name.EndsWith (".csv")) {
					StreamReader sr = null;
					try {
						sr = File.OpenText (fileInfos [i].FullName);
					} catch (Exception e) {
						return;
					}
					List<string> strList = new List<string> ();
					string line;
					while ((line = sr.ReadLine ()) != null) {
						strList.Add (line);
					}
					sr.Close ();
					sr.Dispose ();
					HandleBundle (strList, fileInfos [i].Name);
				}
			}
		}
		maps.Clear ();
		if (AppConst.LuaBundleMode) {
			HandleLuaBundle ();
		} else {
			CopyHandleLuaFile ();
		}
		string resPath = "Assets/" + AppConst.AssetDir;
		BuildPipeline.BuildAssetBundles (resPath, maps.ToArray (), BuildAssetBundleOptions.CollectDependencies, target);
		BuildFileIndex ();

		string streamDir = Application.dataPath + "/" + AppConst.LuaTempDir;
		if (Directory.Exists (streamDir))
			Directory.Delete (streamDir, true);
		AssetDatabase.Refresh ();
	}

	static void AddBuildMap (string bundleName, string pattern, string path)
	{
		string[] files = Directory.GetFiles (path, pattern);
		if (files.Length == 0)
			return;

		for (int i = 0; i < files.Length; i++) {
			files [i] = files [i].Replace ('\\', '/');
		}
		AssetBundleBuild build = new AssetBundleBuild ();
		build.assetBundleName = bundleName;
		build.assetNames = files;
		maps.Add (build);
	}

	/// <summary>
	/// 处理Lua代码包
	/// </summary>
	static void HandleLuaBundle ()
	{
		string streamDir = Application.dataPath + "/" + AppConst.LuaTempDir;
		if (!Directory.Exists (streamDir))
			Directory.CreateDirectory (streamDir);

		string[] srcDirs = { CustomSettings.luaDir, CustomSettings.FrameworkPath + "/ToLua/Lua" };
		for (int i = 0; i < srcDirs.Length; i++) {
			if (AppConst.LuaByteMode) {
				string sourceDir = srcDirs [i];
				string[] files = Directory.GetFiles (sourceDir, "*.lua", SearchOption.AllDirectories);
				int len = sourceDir.Length;

				if (sourceDir [len - 1] == '/' || sourceDir [len - 1] == '\\') {
					--len;
				}
				for (int j = 0; j < files.Length; j++) {
					string str = files [j].Remove (0, len);
					string dest = streamDir + str + ".bytes";
					string dir = Path.GetDirectoryName (dest);
					Directory.CreateDirectory (dir);
					EncodeLuaFile (files [j], dest);
				}    
			} else {
				ToLuaMenu.CopyLuaBytesFiles (srcDirs [i], streamDir);
			}
		}
		string[] dirs = Directory.GetDirectories (streamDir, "*", SearchOption.AllDirectories);
		for (int i = 0; i < dirs.Length; i++) {
			string name = dirs [i].Replace (streamDir, string.Empty);
			name = name.Replace ('\\', '_').Replace ('/', '_');
			name = "lua/lua_" + name.ToLower () + AppConst.ExtName;

			string path = "Assets" + dirs [i].Replace (Application.dataPath, "");
			AddBuildMap (name, "*.bytes", path);
		}
		AddBuildMap ("lua/lua" + AppConst.ExtName, "*.bytes", "Assets/" +AppConst.AppName+"/"+ AppConst.LuaTempDir);

		//-------------------------------处理非Lua文件----------------------------------
		string luaPath = AppDataPath + "/StreamingAssets/lua/";
		for (int i = 0; i < srcDirs.Length; i++) {
			paths.Clear ();
			files.Clear ();
			string luaDataPath = srcDirs [i].ToLower ();
			Recursive (luaDataPath);
			foreach (string f in files) {
				if (f.EndsWith (".meta") || f.EndsWith (".lua"))
					continue;
				string newfile = f.Replace (luaDataPath, "");
				string path = Path.GetDirectoryName (luaPath + newfile);
				if (!Directory.Exists (path))
					Directory.CreateDirectory (path);

				string destfile = path + "/" + Path.GetFileName (f);
				File.Copy (f, destfile, true);
			}
		}
		AssetDatabase.Refresh ();
	}

	/// <summary>
	/// 处理框架实例包
	/// </summary>
	static void HandleExampleBundle ()
	{
		string resPath = AppDataPath + "/" + AppConst.AssetDir + "/";
		if (!Directory.Exists (resPath))
			Directory.CreateDirectory (resPath);

		AddBuildMap ("prompt" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Prompt");
		AddBuildMap ("message" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Message");

		AddBuildMap ("prompt_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Prompt");
		AddBuildMap ("shared_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Shared");
	}

	/// <summary>
	/// 打包资源
	/// </summary>
	public static void HandleBundle (List<string> value, string csvName)
	{
//		MyDebug.LogRed ("csvName = "+csvName);
		csvName = csvName.Substring (0,csvName.IndexOf("."));
		BuildTarget target = getTarget ();
//		MyDebug.LogNormal ("Util.DataPath  = "+Util.DataPath + "/" + csvName);
		if (Directory.Exists (Util.DataPath + "/" + csvName)) {
			Directory.Delete (Util.DataPath + "/" + csvName, true);
		}
		string streamPath = Application.streamingAssetsPath + "/" + csvName;
		if (Directory.Exists (streamPath)) {
			Directory.Delete (streamPath, true);
		}
		MyDebug.LogRed ("streamPath  = "+streamPath);
		Directory.CreateDirectory (streamPath);
		AssetDatabase.Refresh ();

		maps.Clear ();

		for (int i = 0; i < value.Count; i++) {
			string[] temps = value [i].Split (',');
//			MyDebug.LogRed ("value [i] = "+value [i]);
			AddBuildMap (temps [0], temps [1], temps [2]);
		}

		string resPath = "Assets/" + AppConst.AssetDir + "/" + csvName;
		if (!Directory.Exists (resPath))
			Directory.CreateDirectory (resPath);
		BuildPipeline.BuildAssetBundles (resPath, maps.ToArray (), BuildAssetBundleOptions.None, target);
		BuildFileIndex (csvName);

//		string streamDir = Application.dataPath + "/" + AppConst.LuaTempDir;
//		if (Directory.Exists(streamDir)) Directory.Delete(streamDir, true);
//		AssetDatabase.Refresh();

	}

	/// <summary>
	/// 复制Lua文件
	/// </summary>
	public static void CopyHandleLuaFile ()
	{
		string resPath = AppDataPath + "/StreamingAssets/";
		string luaPath = resPath + "/lua/";

		//----------复制Lua文件----------------
		if (!Directory.Exists (luaPath)) {
			Directory.CreateDirectory (luaPath); 
		}
		string[] luaPaths = { AppDataPath + "/"+AppConst.AppName+"/lua/", 
			AppDataPath + "/"+AppConst.AppName+"/Tolua/Lua/"
		};

		for (int i = 0; i < luaPaths.Length; i++) {
			paths.Clear ();
			files.Clear ();
			string luaDataPath = luaPaths [i].ToLower ();
			Recursive (luaDataPath);
			int n = 0;
			foreach (string f in files) {
				if (f.EndsWith (".meta"))
					continue;
				string newfile = f.Replace (luaDataPath, "");
				string newpath = luaPath + newfile;
				string path = Path.GetDirectoryName (newpath);
				if (!Directory.Exists (path))
					Directory.CreateDirectory (path);

				if (File.Exists (newpath)) {
					File.Delete (newpath);
				}
				if (AppConst.LuaByteMode) {
					EncodeLuaFile (f, newpath);
				} else {
					File.Copy (f, newpath, true);
				}
				UpdateProgress (n++, files.Count, newpath);
			} 
		}
		EditorUtility.ClearProgressBar ();
		AssetDatabase.Refresh ();
	}

	static void BuildFileIndex (string csvName = "")
	{
		string resPath = AppDataPath + "/StreamingAssets/";
		///----------------------创建文件列表-----------------------
		if (csvName != "") {
			resPath +=  csvName+"/";
		}
		string newFilePath = resPath + "files.txt";
		if (File.Exists (newFilePath))
			File.Delete (newFilePath);

		paths.Clear ();
		files.Clear ();
		Recursive (resPath);

		FileStream fs = new FileStream (newFilePath, FileMode.CreateNew);
		StreamWriter sw = new StreamWriter (fs);
		for (int i = 0; i < files.Count; i++) {
			string file = files [i];
			string ext = Path.GetExtension (file);
			if (file.EndsWith (".meta") || file.Contains (".DS_Store"))
				continue;

			string md5 = Util.md5file (file);
			string value = file.Replace (resPath, string.Empty);
			sw.WriteLine (value + "|" + md5);
		}
		sw.Close ();
		fs.Close ();
	}

	/// <summary>
	/// 数据目录
	/// </summary>
	static string AppDataPath {
		get { return Application.dataPath.ToLower (); }
	}

	/// <summary>
	/// 遍历目录及其子目录
	/// </summary>
	static void Recursive (string path)
	{
		string[] names = Directory.GetFiles (path);
		string[] dirs = Directory.GetDirectories (path);
		foreach (string filename in names) {
			string ext = Path.GetExtension (filename);
			if (ext.Equals (".meta"))
				continue;
			files.Add (filename.Replace ('\\', '/'));
		}
		foreach (string dir in dirs) {
			paths.Add (dir.Replace ('\\', '/'));
			Recursive (dir);
		}
	}

	static void UpdateProgress (int progress, int progressMax, string desc)
	{
		string title = "Processing...[" + progress + " - " + progressMax + "]";
		float value = (float)progress / (float)progressMax;
		EditorUtility.DisplayProgressBar (title, desc, value);
	}

	public static void EncodeLuaFile (string srcFile, string outFile)
	{
		if (!srcFile.ToLower ().EndsWith (".lua")) {
			File.Copy (srcFile, outFile, true);
			return;
		}
		bool isWin = true; 
		string luaexe = string.Empty;
		string args = string.Empty;
		string exedir = string.Empty;
		string currDir = Directory.GetCurrentDirectory ();
		if (Application.platform == RuntimePlatform.WindowsEditor) {
			isWin = true;
			luaexe = "luajit.exe";
			args = "-b -g " + srcFile + " " + outFile;
			exedir = AppDataPath.Replace ("assets", "") + "LuaEncoder/luajit/";
		} else if (Application.platform == RuntimePlatform.OSXEditor) {
			isWin = false;
			luaexe = "./luajit";
			args = "-b -g " + srcFile + " " + outFile;
			exedir = AppDataPath.Replace ("assets", "") + "LuaEncoder/luajit_mac/";
		}
		Directory.SetCurrentDirectory (exedir);
		ProcessStartInfo info = new ProcessStartInfo ();
		info.FileName = luaexe;
		info.Arguments = args;
		info.WindowStyle = ProcessWindowStyle.Hidden;
		info.UseShellExecute = isWin;
		info.ErrorDialog = true;
		Util.Log (info.FileName + " " + info.Arguments);

		Process pro = Process.Start (info);
		pro.WaitForExit ();
		Directory.SetCurrentDirectory (currDir);
	}

	[MenuItem ("LuaFramework/ProtoBuf生成Lua文件", false, 3)]
	public static void BuildProtobufFile ()
	{
//		if (!AppConst.ExampleMode) {
//			UnityEngine.Debug.LogError ("若使用编码Protobuf-lua-gen功能，需要自己配置外部环境！！");
//			return;
//		}
		string dir = AppDataPath+"/"+AppConst.AppName + "/Lua/ProtoBuffer/build";
		paths.Clear ();
		files.Clear ();
		Recursive (dir);
		//protoc , protoc_gen_dir 请根据自己本地的protoc路径自行配置 
		string protoc = "D:/myTools/protoBuffer/protobuf-2.4.1/src/protoc.exe";
		string protoc_gen_dir = "\"D:/myTools/protoBuffer/protoc-gen-lua-master/plugin/protocGen.bat\"";
		if (files.Count > 0) {
			foreach (string f in files) {
				string name = Path.GetFileName (f);
				string ext = Path.GetExtension (f);
				if (!ext.Equals (".proto"))
					continue;

				ProcessStartInfo info = new ProcessStartInfo ();
				info.FileName = protoc;
				info.Arguments = " --proto_path=" + dir + " --lua_out=" + dir + "/ --plugin=protoc-gen-lua=" + protoc_gen_dir + " " + dir + "/" + name;
				info.WindowStyle = ProcessWindowStyle.Hidden;
				info.UseShellExecute = true;
				info.WorkingDirectory = dir;
				info.ErrorDialog = true;
				Util.Log (dir + "/" + name);

				Process pro = Process.Start (info);
				pro.WaitForExit ();
			}
			AssetDatabase.Refresh ();
		} else {
			MyDebug.LogNormal ("没有找到文件");
		}
	}
}